home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / mg / rexx / config.rexx < prev    next >
OS/2 REXX Batch file  |  1995-03-09  |  6KB  |  242 lines

  1. /*
  2.  * config - used to set up option files for programs with to many conditional
  3.  *    compilation defines.
  4.  *
  5.  *    copyright (c) 1989, Mike Meyer
  6.  *
  7.  * Usage: config <configfile>
  8.  *    .h files are generated in /<configfile> setting the options
  9.  *    as specified in <configfile>. But first, config.options is
  10.  *    read to find out what options you can & can't set for the
  11.  *    program being configed. See config.doc and make-config.doc
  12.  *    for details.
  13.  */
  14.  
  15. /*
  16.  * There are three magic globals - options, required and actions. required
  17.  *    keeps track of the options that you _have_ to specify, and whether
  18.  *    it's seen them or not. options keeps track of the options you can
  19.  *    specify, and the current value. The syntax for both is the
  20.  *    same: X.<name> holds the value of option <name>, or whether
  21.  *    required.<name> has been seen or not. Since there's no easy
  22.  *    way to walk through all the members on a stem (yet), we also
  23.  *    have to keep track of the names. They are stored in X.1 through
  24.  *    X.N, where there are currently N names in X. Just to keep everything
  25.  *    in one place, N is kept in X.0. Actions keeps track of any actions
  26.  *    that have been specified. Since they have no names, the actions
  27.  *    themselves are tracked in actions.N, with actions.0 holding the
  28.  *    number of actions specified.
  29.  */
  30.  
  31. /*
  32.  * Main routine - initialize the globals, read in the base config file,
  33.  *    read in and apply the options the user selects, then write the
  34.  *    appropriate include files out.
  35.  */
  36.  
  37. arg system
  38. undefined = '/\/\.* '        /* value for options not in .options files */
  39. namerequired = '/\...* '    /* value for required options not yet used */
  40. options. = undefined         /* none are defined yet */
  41. required. = undefined        /* Haven't seen it yet */
  42.  
  43. options.0 = 0            /* No options yet */
  44. required.0 = 0            /* and no required options */
  45. actions.0 = 0            /* and no actions */
  46.  
  47. if system = "" then do
  48.     say "usage: config CONFIGFILE"
  49.     exit 10
  50.     end
  51.  
  52. if ~open(basefile, 'config.options', 'Read') then do
  53.     say "Can't find config base"
  54.     exit 20
  55.     end
  56. call buildoptions basefile
  57. call close basefile
  58.  
  59. if ~open(configfile, system, 'Read') then do
  60.     say "Can't find config file" system
  61.     exit 20
  62.     end
  63. call applyoptions configfile
  64. call close configfile
  65.  
  66. call dumpoptions system
  67. exit 0
  68.  
  69. /*
  70.  * buildoptions - given an input file, it builds the option & required data
  71.  *    structure for that file.
  72.  */
  73. buildoptions: procedure expose options. required. actions. namerequired
  74.     arg    optfile
  75.  
  76.     do forever
  77.         call readline optfile
  78.         if eof(optfile) & name = "" then leave
  79.         if name == 'action' then do
  80.             new = getnextaction()
  81.             actions.new = value
  82.             end
  83.         else if value ~= 'required' then do
  84.             new = getnextoption()
  85.             options.new = name
  86.             if value = 'option' then value = 'off'
  87.             options.name = value
  88.             end
  89.         else do
  90.             new = getnextrequired()
  91.             required.new = name
  92.             required.name = namerequired
  93.             end
  94.         end
  95.     return
  96.  
  97. /*
  98.  * applyoptions - given a file, we apply each option line to the existing
  99.  *    database.
  100.  */
  101. applyoptions: procedure expose options. required. actions. undefined namerequired
  102.     arg    optfile
  103.  
  104.     requireddone = 0
  105.     do forever
  106.         call readline optfile
  107.         if eof(optfile) & name = "" then leave
  108.         if name = 'option' then do
  109.             name = value
  110.             value = 'on'
  111.             end
  112.         if options.name ~= undefined then do
  113.             if ~requireddone then do
  114.                 requireddone = checkrequire()
  115.                 if ~requireddone then do
  116.                     say "Option" name "specified before required options"
  117.                     exit 10
  118.                     end
  119.                 end
  120.             options.name = value
  121.             end
  122.         else if required.name ~= undefined then do
  123.             if required.name ~= namerequired then do
  124.                 say 'Required' name 'seen twice.'
  125.                 exit 10
  126.                 end
  127.             required.name = value
  128.             if ~open(reqfile, value || '.options', 'Read') then do
  129.                 say "Invalid value:" value "for option:" name
  130.                 exit 20
  131.                 end
  132.             call buildoptions reqfile
  133.             call close reqfile
  134.             end
  135.         else say 'Unkown option' name 'ignored.'
  136.         end
  137.     return
  138.  
  139. /*
  140.  * dumpoptions - output the include files as specified by this config file.
  141.  */
  142. dumpoptions: procedure expose options. required. actions.
  143.     arg    conf
  144.  
  145.  
  146.     if ~exists('/' || conf) then 'makedir /' || conf
  147.  
  148.     do i=1 to options.0
  149.         name = options.i
  150.         if options.name = 'off' then out = ""
  151.         else if options.name = 'on' then out = "#define" upper(name)
  152.         else out = "#define" upper(name) options.name
  153.         call dumpinc conf, name, out
  154.         end
  155.  
  156.     do i=1 to required.0
  157.         name = required.i
  158.         out = "#define" upper(required.name)
  159.         call dumpinc conf, name, out
  160.         end
  161.  
  162.     'cd /' || conf
  163.     do i=1 to actions.0
  164.         actions.i
  165.         end
  166.     return
  167.  
  168. /*
  169.  * readline - read a line in, and put the appropriate parts in the globals
  170.  *    'name' and 'value'.
  171.  */
  172. readline: procedure expose name value
  173.     arg file
  174.  
  175.     do forever
  176.         line = translate(readln(file), " ", "    ")    /* tabs */
  177.         parse var line name value "# "
  178.         if name ~= "#" & name ~= "" then leave
  179.         if eof(file) then do
  180.             name = ""
  181.             return
  182.             end
  183.         end
  184.     value = strip(value)
  185.     return
  186. /*
  187.  * getnextoption - returns the number for the next free option.
  188.  */
  189. getnextoption: procedure expose options.0
  190.  
  191.     options.0 = options.0 + 1
  192.     return options.0
  193.  
  194. /*
  195.  * getnextrequired - returns the number for the next free required.
  196.  */
  197. getnextrequired: procedure expose required.0
  198.  
  199.     required.0 = required.0 + 1
  200.     return required.0
  201.  
  202. /*
  203.  * getnextaction - returns the number for the next free action.
  204.  */
  205. getnextaction: procedure expose actions.0
  206.  
  207.     actions.0 = actions.0 + 1
  208.     return actions.0
  209.  
  210. /*
  211.  * checkrequire - return 1 if all required options have been seen, 0
  212.  *    otherwise.
  213.  */
  214. checkrequire: procedure expose required. namerequired
  215.  
  216.     do i=1 to required.0
  217.         name = required.i
  218.         if required.name = namerequired then return 0
  219.         end
  220.     return 1
  221.  
  222. /*
  223.  * dumpinc - creates a new include file, but only if it's different from
  224.  *    the current one.
  225.  */
  226. dumpinc: procedure
  227.     parse arg dir, file, line
  228.  
  229.     name = '/' || dir || '/' || file || ".h"
  230.     if open(incfile, name, 'Read') then do
  231.         old = readln(incfile)
  232.         call close incfile
  233.         if old = line then return
  234.         end
  235.     if ~open(incfile, name, 'Write') then do
  236.         say "Can't create include file" name
  237.         return
  238.         end
  239.     call writeln incfile, line
  240.     call close incfile
  241.     return
  242.